<template>
  <el-table
    ref="aTableRef"
    :class="[
      'al-table',
      {
        'no-all-select': config.noAllSelect,
        'mini-distance': config.isMiniDistance,
        'mx-sortable': config.isSortable,
        'table-single-select': config.isSingleSelect,
      },
    ]"
    :data="tableData"
    :header-cell-style="headerCellStyle"
    :cell-style="cellStyle"
    :row-class-name="rowClassName"
    :cell-class-name="cellClassName"
    empty-text="No Data"
    v-loading="loading"
    v-bind="config"
    @cell-dblclick="cellDblclick"
    @selection-change="handleSelectionChange"
    @current-change="handleCurrentRowChange"
    @select="handleSelect"
    @select-all="handleSelectAll"
    @header-contextmenu="handleHeaderContextmenu"
    @cell-contextmenu="handleCellContextmenu"
    @row-click="rowClick"
  >
    <template v-if="config.isEmpty" #empty>
      <span :class="[config.class ? config.class : tableText]">{{ config.emptyContent }}</span>
    </template>
    <!--  选择/序号  -->
    <el-table-column
      v-for="column in typeList"
      :key="column.type"
      :type="column.type"
      :label="column.label"
      label-class-name="ignore"
      v-bind="{ align: 'center', width: 60, ...column.itemConfig }"
    />
    <!-- @slot 表格起始插槽 -->
    <slot name="prepend" />
    <!--  表格主体内容  -->
    <TableRecursion
      v-for="(column, index) in columnList"
      :key="index"
      :column="column"
      @itemEvent="itemEvent"
    >
      <template #headerColumn="{ scope, column, headerColumnConfig }">
        <slot
          :name="headerColumnConfig.prop"
          :scope="scope"
          :column="column"
          :headerColumnConfig="headerColumnConfig"
        ></slot>
      </template>
      <template #column="{ scope, column }">
        <slot name="column" :scope="scope" :column="column"></slot>
      </template>
    </TableRecursion>
    <!-- @slot 表格末尾插槽 -->
    <slot name="append" />
  </el-table>
</template>

<script setup>
import TableRecursion from './item/TableRecursion.vue';
import { nextTick } from 'vue';

let props = defineProps({
  /**
   * 表格列配置
   */
  tableList: {
    type: Array,
    default: () => [],
  },
  /**
   * 表格配置
   */
  tableConfig: {
    type: Object,
    default: () => ({}),
  },
  /**
   * 获取当前行索引
   */
  rowClassName: {
    type: Function,
    default: ({ row, rowIndex }) => {
      row.index = rowIndex;
    },
  },

  tableData: {
    type: Array,
    default: () => [],
  },
  cellClassName: {
    // 当前单元格索引
    type: Function,
    default: ({ row, column, rowIndex, columnIndex }) => {},
  },
  loading: {
    type: Boolean,
    default: false,
  },
});

const emits = defineEmits([
  'cellDblclick',
  'handleSelectionChange',
  'handleCurrentRowChange',
  'handleCellContextmenu',
  'handleHeaderContextmenu',
  'handleSingleSelect',
  'handleSelect',
  'handleSelectAll',
  'tableEvent',
  'rowClick',
]);

let columnList = ref([]);
let typeList = ref([]);
let timer = ref(null);
let tableText = ref('table-text');
let cellStyle = ref({
  padding: '0',
  height: '32px',
  fontSize: '12px',
});
let headerCellStyle = ref({
  padding: '0',
  height: '32px',
  fontSize: '12px',
  color: '#303133',
});

const aTableRef = ref();

const config = computed(() => {
  return {
    noAllSelect: false,
    isMiniDistance: true,
    isSortable: false,
    border: true,
    stripe: false,
    highlightCurrentRow: true,
    size: '',
    isSingleSelect: false, // 是否单选
    ...props.tableConfig,
  };
});

onMounted(() => {
  initTable();
});
onUpdated(() => {
  if (timer.value) {
    clearInterval(timer.value);
  }
  timer.value = setTimeout(() => {
    doLayout();
  }, 100);
});

/**
 * 初始化表格
 * tableList 中配置除 type = button 之外 type 项会渲染成 element-ui type 项
 * tableList 中配置 prop 项会渲染成 表格自定义项
 */
let initTable = () => {
  let typeListArr = [];
  let columnListArr = [];
  let isType = false;
  props.tableList.forEach(item => {
    if (item?.type) {
      isType = true;
      typeListArr.push(item);
    } else {
      columnListArr.push(item);
    }
  });
  if (isType) typeList.value = typeListArr;
  columnList.value = columnListArr;
};

function cellDblclick(row, column, cell, event) {
  /**
   * 当某一行被双击时会触发该事件
   *
   * @event cellDblclick
   */
  emits('cellDblclick', row, column, cell, event);
}

// 当某行被点击时触发
function rowClick(row, column, event) {
  emits('rowClick', row, column, event);
}

function handleSelectionChange(val, row) {
  /**
   * 当选择项发生变化时会触发该事件
   *
   * @event handleSelectionChange
   * @param {Array} val 当前选择项
   */
  emits('handleSelectionChange', val, row);
}
function handleCurrentRowChange(currentRow, oldCurrentRow) {
  /**
   * 当选择行发生变化时会触发该事件
   *
   * @event handleCurrentRowChange
   * @param {Object} currentRow 当前选择行
   * @param {Object} oldCurrentRow 上次选择行
   */
  emits('handleCurrentRowChange', currentRow, oldCurrentRow);
}

function handleCellContextmenu(row, column, cell, event) {
  /**
   * 当某个单元格被鼠标右键点击时会触发该事件
   *
   * @param {Object} row 当前单击行
   * @param {Object} column
   * @param {Object} cell
   * @param {Object} event
   */
  emits('handleCellContextmenu', row, column, cell, event);
}
function handleHeaderContextmenu(column, event) {
  /**
   * 当某一列的表头被鼠标右键点击时触发该事件
   *
   * @event handleSelectionChange
   * @param {Object} column
   * @param {Object} event
   */
  emits('handleHeaderContextmenu', column, event);
}

function handleSelect(selection, row) {
  /**
   * 当用户手动勾选数据行的 Checkbox 时触发的事件
   *
   * @event handleSelect
   */
  if (config.value.isSingleSelect) {
    aTableRef.value.clearSelection();
    if (selection.length == 0) {
      emits('handleSingleSelect', {});
      return;
    }
    aTableRef.value.toggleRowSelection(row, true);
    emits('handleSingleSelect', row);
    return;
  }
  emits('handleSelect', selection, row);
}
function handleSelectAll(selection) {
  /**
   * 当用户手动勾选全选 Checkbox 时触发的事件
   *
   * @event handleSelectAll
   */
  emits('handleSelectAll', selection);
}
function toggleSelection(rows) {
  if (rows) {
    rows.forEach(row => {
      toggleRowSelection(row);
    });
  } else {
    aTableRef.value.clearSelection();
  }
}
function toggleRowSelection(row) {
  nextTick(() => {
    aTableRef.value.toggleRowSelection(row);
  });
}

// table子组件触发事件
let itemEvent = data => {
  emits('tableEvent', data);
};

// 设置勾选默认选中
function initSelect({ idKey = 'id', selectList = [] }) {
  nextTick(() => {
    props.tableData.forEach(item => {
      aTableRef.value.toggleRowSelection(item, selectList.indexOf(item[idKey]) > -1);
    });
  });
}
// 清除选择
function clearSelection() {
  nextTick(() => {
    aTableRef.value.clearSelection();
  });
}

function setCurrentRow(row) {
  // 选中当前行
  aTableRef.value.setCurrentRow(row);
}

function setBindConfig(prop, bindProp, value) {
  let propFormItem = props.tableList.find(item => item.prop === prop);
  let bindConfig = propFormItem && propFormItem.bindConfig.bindConfig;
  if (bindConfig) bindConfig[bindProp] = value;
}

// 重新更新table
function doLayout() {
  nextTick(() => {
    if (aTableRef.value) {
      aTableRef.value.doLayout();
    }
  });
}

defineExpose({
  initTable,
  doLayout,
  initSelect,
  toggleSelection,
  toggleRowSelection,
  clearSelection,
  setCurrentRow,
  setBindConfig,
});
</script>

<style lang="scss" scoped>
:deep() {
  .el-table__header {
    th {
      background-color: #f5f5f5 !important;
    }
    .el-table__cell {
      font-weight: 500;
    }
  }
  .el-input,
  .el-input__wrapper,
  .el-input-number,
  .el-select,
  .el-table__cell .el-input {
    width: 99.8%;
  }
}
.table-single-select :deep() {
  th.el-table__cell:nth-child(1) .cell {
    visibility: hidden;
  }
}
</style>
